package PrjDBUtils

import (
	"database/sql"
	db_utils "dgo/goutils/db-utils"
	"dgo/goutils/utils"
	"errors"
	"gitee.com/ymofen/supervalue"
	"strings"
	"time"
)

var (
	Config_LowerFieldName bool = true // 打包时转换成小写
)

// 判断如果req中存在值就进行更新
func CheckSetUpdateValAsStringFromJSON2(recB *db_utils.RecUpdateUpbuilder, req *wrapper.SuperValue, dbkeyfield,
	jsonkey string) string {
	if len(jsonkey) == 0 {
		jsonkey = dbkeyfield
	}
	v := req.ValueByName(jsonkey)
	if v != nil {
		v1 := v.String()
		recB.SetValue(dbkeyfield, v1)
		return v1
	} else {
		return ""
	}
}

// 判断如果req中存在值就进行更新
func CheckSetUpdateValAsInt2(UB *db_utils.RecUpdateUpbuilder, req *wrapper.SuperValue, dbkeyfield, jsonkey string, errDef int64) int64 {
	if len(jsonkey) == 0 {
		jsonkey = dbkeyfield
	}
	v := req.Find(jsonkey)
	if v != nil {
		v1 := v.Int64()
		UB.SetValue(dbkeyfield, v1)
		return v1
	} else {
		return 0
	}
}

func CheckSetUpdateValAsDateTime2(UB *db_utils.RecUpdateUpbuilder, req *wrapper.SuperValue, dbkeyfield, jsonkey string, errDef time.Time) time.Time {
	if len(jsonkey) == 0 {
		jsonkey = dbkeyfield
	}
	v := req.Find(jsonkey)
	if v != nil {
		str := v.String()
		v1 := utils.TryStrToTime(str, time.Local, errDef)
		UB.SetValue(dbkeyfield, v1)
		return v1
	} else {
		return utils.ZeroTime
	}
}

func JsonCopyFromRowsValueList2(json *wrapper.SuperValue, rows [][]db_utils.SqlValue, idx int) error {
	if len(rows) == 0 {
		return nil
	}

	ForeachRows(rows, func(row []db_utils.SqlValue, k int) bool {
		json.SetIndexValue(-1, ExtractSQLValue(row[idx].Value))
		return true
	})
	return nil
}

func JsonCopyFromRowsAndColumn2(jsonArray *wrapper.SuperValue, rows [][]db_utils.SqlValue, columns []string) error {
	if len(rows) == 0 {
		return nil
	}
	if len(columns) < len(rows[0]) {
		return errors.New("columns is less than row")
	}

	for _, v := range rows {
		itm := jsonArray.AppendObject()
		JsonCopyFromRowAndColumnWithCb2(itm, v, columns, nil)
	}
	return nil
}

func JsonCopyFromRowsAndColumnWithCb2(json *wrapper.SuperValue, rows [][]db_utils.SqlValue, columns []string,
	eachFieldCb func(rec *wrapper.SuperValue, k string, v interface{}, row []db_utils.SqlValue) (ignore bool, key string, val interface{})) error {
	if len(rows) == 0 {
		return nil
	}
	if len(columns) < len(rows[0]) {
		return errors.New("columns is less than row")
	}

	for _, v := range rows {
		itm := json.AppendObject()
		JsonCopyFromRowAndColumnWithCb2(itm, v, columns, eachFieldCb)
	}
	return nil
}

type TPreProcessRecCB func(rec *wrapper.SuperValue, k *string, v *interface{}, rowval []db_utils.SqlValue, ignore *bool)

func JsonCopyFromRows(json *wrapper.SuperValue, rows *sql.Rows, preProcess TPreProcessRecCB) error {
	vals, cols, err := db_utils.ExtractRowsAndColumns(rows)
	if err != nil {
		return err
	}
	return JsonCopyFromRowsAndColumnWithCb3(json, vals, cols, preProcess)
}

/***
  和 JsonCopyFromRowsAndColumnWithCb2 一致,只是getter不一样
*/

func JsonCopyFromRowsAndColumnWithCb3Ex(json *wrapper.SuperValue, rows [][]db_utils.SqlValue, columns []string,
	preProcess TPreProcessRecCB, lowerfieldnameflag bool) error {
	if len(rows) == 0 {
		return nil
	}
	if len(columns) < len(rows[0]) {
		return errors.New("columns is less than row")
	}

	for _, v := range rows {
		itm := json.AppendObject()
		JsonCopyFromRowAndColumnWithCb0(itm, v, columns, preProcess, lowerfieldnameflag)
	}
	return nil
}

func JsonCopyFromRowsAndColumnWithCb3(json *wrapper.SuperValue, rows [][]db_utils.SqlValue, columns []string,
	preProcess TPreProcessRecCB) error {
	return JsonCopyFromRowsAndColumnWithCb3Ex(json, rows, columns, preProcess, Config_LowerFieldName)
}

func JsonCopyFromRowAndColumnWithCb0(json *wrapper.SuperValue, row []db_utils.SqlValue, columns []string, preProcess TPreProcessRecCB, lowerfieldnameflag bool) error {
	if len(columns) < len(row) {
		return errors.New("columns is less than row")
	}

	for k, v1 := range row {
		strKey := columns[k]
		if lowerfieldnameflag {
			strKey = strings.ToLower(strKey)
		}
		realV := v1.Value
		if preProcess != nil {
			ignore := false
			preProcess(json, &strKey, &realV, row, &ignore)
			if ignore {
				continue
			}
		}

		switch s := realV.(type) {
		case []byte:
			if len(s) == 1 {
				if s[0] == 0 {
					json.SetKeyBool(strKey, false)
					break
				} else if s[0] == 1 {
					json.SetKeyBool(strKey, true)
					break
				}
			}
			json.SetKeyString(strKey, string(s))
		case time.Time:
			json.SetKeyString(strKey, utils.DateTimeString3(s))
		case nil:
			break
		default:
			json.SetKeyValue(strKey, realV)
		}
	}

	return nil
}

/*
**

	和 JsonCopyFromRowAndColumnWithCb2 一致,只是getter不一样
*/
func JsonCopyFromRowAndColumnWithCb3(json *wrapper.SuperValue, row []db_utils.SqlValue, columns []string, preProcess TPreProcessRecCB) error {
	return JsonCopyFromRowAndColumnWithCb0(json, row, columns, preProcess, Config_LowerFieldName)
}

func JsonCopyFromRowAndColumnWithCb2(json *wrapper.SuperValue,
	row []db_utils.SqlValue, columns []string,
	getter func(rec *wrapper.SuperValue, k string, v interface{}, rowval []db_utils.SqlValue) (ignore bool, key string, val interface{})) error {
	if len(columns) < len(row) {
		return errors.New("columns is less than row")
	}

	for k, v1 := range row {
		strKey := columns[k]
		if Config_LowerFieldName {
			strKey = strings.ToLower(strKey)
		}
		realV := v1.Value
		if getter != nil {
			ignore := false
			ignore, strKey, realV = getter(json, strKey, realV, row)
			if ignore {
				continue
			}
		}

		switch s := realV.(type) {
		case []byte:
			if len(s) == 1 {
				if s[0] == 0 {
					json.SetKeyBool(strKey, false)
					break
				} else if s[0] == 1 {
					json.SetKeyBool(strKey, true)
					break
				}
			}
			json.SetKeyString(strKey, string(s))
		case time.Time:
			json.SetKeyString(strKey, utils.DateTimeString3(s))
		case nil:
			break
		default:
			json.SetKeyValue(strKey, realV)
		}
	}

	return nil
}

// 判断如果req中存在值就进行更新
func CheckSetUpdateVal2(UB *db_utils.RecUpdateUpbuilder, req *wrapper.SuperValue, dbkeyfield, jsonkey string) {
	if len(jsonkey) == 0 {
		jsonkey = dbkeyfield
	}
	v := req.VarByName(jsonkey)
	if v != nil {
		UB.SetValue(dbkeyfield, v)
	}
}
